package com.example.service;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * 分布式锁服务
 */
@Service
@Slf4j
public class LockService {

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 获取锁并执行操作
     * 
     * @param lockKey 锁键
     * @param waitTime 等待获取锁的最大时间
     * @param leaseTime 持有锁的时间，超过时间自动释放
     * @param unit 时间单位
     * @param runnable 获取锁后执行的操作
     * @return 是否成功执行
     */
    public boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit, Runnable runnable) {
        RLock lock = redissonClient.getLock(lockKey);
        boolean locked = false;
        try {
            locked = lock.tryLock(waitTime, leaseTime, unit);
            if (locked) {
                log.debug("获取锁成功: {}", lockKey);
                runnable.run();
                return true;
            } else {
                log.warn("获取锁失败: {}", lockKey);
                return false;
            }
        } catch (InterruptedException e) {
            log.error("获取锁被中断: {}", lockKey, e);
            Thread.currentThread().interrupt();
            return false;
        } catch (Exception e) {
            log.error("执行锁定操作异常: {}", lockKey, e);
            return false;
        } finally {
            if (locked) {
                try {
                    lock.unlock();
                    log.debug("释放锁: {}", lockKey);
                } catch (Exception e) {
                    log.error("释放锁异常: {}", lockKey, e);
                }
            }
        }
    }

    /**
     * 获取锁并执行操作（使用默认等待和租约时间）
     * 
     * @param lockKey 锁键
     * @param runnable 获取锁后执行的操作
     * @return 是否成功执行
     */
    public boolean tryLock(String lockKey, Runnable runnable) {
        return tryLock(lockKey, 5, 30, TimeUnit.SECONDS, runnable);
    }

    /**
     * 获取元数据更新锁并执行操作
     * 
     * @param metadataKey 元数据键
     * @param runnable 获取锁后执行的操作
     * @return 是否成功执行
     */
    public boolean tryMetadataLock(String metadataKey, Runnable runnable) {
        return tryLock("metadata_lock:" + metadataKey, 10, 60, TimeUnit.SECONDS, runnable);
    }

    /**
     * 获取缓存更新锁并执行操作
     * 
     * @param cacheKey 缓存键
     * @param runnable 获取锁后执行的操作
     * @return 是否成功执行
     */
    public boolean tryCacheLock(String cacheKey, Runnable runnable) {
        return tryLock("cache_lock:" + cacheKey, 5, 30, TimeUnit.SECONDS, runnable);
    }
} 